import ast
import math
import statistics
from flask import Blueprint,  request
import numpy as np
from scipy.stats import kurtosis, skew


descriptiveStatistics_api=Blueprint('descriptiveStatistics_api',__name__)

# 描述统计

# 通用函数
# -----------------------------------------------------------------------------------
# 计算频率
def elemFreq(arr):
    freq_dict = {}
    for i in arr:
        freq_dict[i] = freq_dict.get(i, 0) + 1
    # 将字典中的键值对转换为元组形式，以便进行排序
    freq_tuples = [(num, count) for num, count in freq_dict.items()]
    # 以出现次数作为排序关键字，进行降序排序
    sorted_freq = sorted(freq_tuples, key=lambda x: x[1], reverse=True)
    return sorted_freq

# 计算均值
def mean(arr):
    return sum(arr) / len(arr)

 # 计算中位数
def median(arr):
    arr.sort()
    mid = len(arr) // 2
    if len(arr) % 2 == 0:
        return (arr[mid-1] + arr[mid]) / 2
    else:
        return arr[mid]
# 计算众数
def mode(arr):
    mode = statistics.mode(arr)

    return mode


# 计算全距
def range(arr):
    return max(arr) - min(arr)

# 计算百分位差
def calc_percentile(data, percentile):
    """
    计算指定百分位数

    参数：
    data: 数组，需要计算百分位数的数据
    percentile: float，百分位数，取值范围为0到100

    返回值：
    指定百分位数的值
    """
    return np.percentile(data, percentile)

def calc_percentile_range(data1, data2, percentile):
    """
    计算两个数据集的百分位差

    参数：
    data1: 数组，第一个数据集
    data2: 数组，第二个数据集
    percentile: float，百分位数，取值范围为0到100

    返回值：
    两个数据集在指定百分位数上的差值
    """
    return calc_percentile(data1, percentile) - calc_percentile(data2, percentile)
# 测试案例
# data1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# data2 = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
# percentile = 50
#
# print(calc_percentile_range(data1, data2, percentile))  # 输出：-1.0

# 计算四分位差
def quartileRange(arr):
    q1 = np.percentile(arr, 25)  # 计算第一四分位数
    q3 = np.percentile(arr, 75)  # 计算第三四分位数
    iqr = q3 - q1  # 计算四分位差
    return iqr

# 计算指定分位数
def percentile(arr, p):
    return np.percentile(arr, p)

# 计算方差
def variance(arr):
    return np.var(arr)

# 计算标准差
def stdDev(arr):
    return np.std(arr)

# 计算峰度
def kurtosiz(arr):
    return kurtosis(arr)

# 计算偏度
def skewness(arr):
    return skew(arr)



# -----------------------------------------------------------------------------------

# 计算所有集中量数
# 返回包括:频次、均分、中数、众数
@descriptiveStatistics_api.route("calCCTTall",methods=["POST"])
def caalCcttAll():
    array=request.form.get('array')
    # str转list
    array =ast.literal_eval(array)

    elemFreqd = elemFreq(array)
    mediand =median(array)

    moded = mode(array)
    meand = mean(array)
    print(elemFreqd,mediand)

    return {"elemFreq":elemFreqd,"median":mediand,"mode":moded,"mean":meand}



# 计算所有集中量数
# 返回包括:频次、均分、中数、众数中特定的某个值
@descriptiveStatistics_api.route("calCCTTvalue",methods=["POST"])
def caalCcttOne():
    valueType = request.form.get('valueType')
    array = request.form.get('array')
    array = ast.literal_eval(array)


    elemFreqd = elemFreq(array)
    mediand = median(array)
    moded = mode(array)
    meand = mean(array)

    if valueType=="elemFreq":
        return {"elemFreq":elemFreqd}
    elif valueType=="mean":
        print(meand)
        return {"mean":meand}
    elif valueType=="median":
        return  {"median":mediand}
    elif valueType=="mode":
        return {"mode":moded}
    else:
        return "输入类型有误"



# 计算所有差异量数
# 返回包括:全距、百分位差、四分位差、指定分位数、方差、标准差、峰度、偏度
@descriptiveStatistics_api.route("calDIFFall",methods=["POST"])
def c2():
    # 获取请求变量
    array1 = request.form.get('array1')
    array1 = ast.literal_eval(array1)

    # p为百分位数
    p=request.form.get("p")
    p=float(p)

    array2 = request.form.get('array2')
    array2 = ast.literal_eval(array2)

    # print(array1,array2,p)

    vrange = range(array1)
    vcalc_percentile_range=calc_percentile_range(array1,array2,p)
    vquartileRange= quartileRange(array1)
    vpercentile= percentile(array1,p)
    vvariance=variance(array1)
    vstdDev=stdDev(array1)
    vkurtosiz=kurtosiz(array1)
    vskewness=skewness(array1)

    return {
        "range":vrange,
        "calc_percentile_range":vcalc_percentile_range,
        "quartileRange":vquartileRange,
        "percentile":vpercentile,
        "variance":vvariance,
        "stdDev":vstdDev,
        "kurtosiz":vkurtosiz,
        "skewness":vskewness
    }


# 计算所有差异量数
# 返回"全距、百分位差、四分位差、指定分位数、方差、标准差、峰度、 偏度"中特定的某个值
@descriptiveStatistics_api.route("calDIFFvalue",methods=["POST"])
def c():
    # 获取请求变量
    array1 = request.form.get('array1')
    array1 = ast.literal_eval(array1)
    valueType = request.form.get("valueType")

    if valueType=="range":
        return {"range": range(array1)}
    elif valueType=="quartileRange":
        vquartileRange = quartileRange(array1)
        return  {"quartileRange":vquartileRange}
    elif valueType == "variance":
        vvariance = variance(array1)
        return  {"variance":vvariance}
    elif valueType == "stdDev":
        vstdDev = stdDev(array1)
        return  {"stdDev":vstdDev}
    elif valueType == "kurtosiz":
        vkurtosiz = kurtosiz(array1)
        return {"kurtosiz":vkurtosiz}
    elif valueType == "skewness":
        vskewness = skewness(array1)
        return  {"skewness":vskewness}
    else:
        # p为百分位数
        p = request.form.get("p")
        p = float(p)

        if valueType == "percentile":
            vpercentile = percentile(array1, p)
            return {"percentile":vpercentile}
        elif valueType == "calc_percentile_range":
            array2 = request.form.get('array2')
            array2 = ast.literal_eval(array2)
            vcalc_percentile_range = calc_percentile_range(array1, array2, p)
            return {"calc_percentile_range":vcalc_percentile_range}








